package main.com.sun.jeecgexam.struts.servlet;

import main.com.sun.jeecgexam.struts.action.Action;
import main.com.sun.jeecgexam.struts.config.ConfigParseUtil;
import main.com.sun.jeecgexam.struts.form.ActionForm;
import main.com.sun.jeecgexam.struts.mapping.ActionForward;
import main.com.sun.jeecgexam.struts.mapping.ActionMapping;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.Map;

/**
 * Created by sun on 2017/3/28.
 */
public class StrutsServlet extends HttpServlet {

    @Override
    public void init() throws ServletException {
        // 首先从ServletContext中判断struts-config配置文件是否已经加载过了
        if (String.valueOf(this.getServletContext().getAttribute("StrutsConfigLoaded")).equals("1")) {
            return;
        }

        // 初始化该servlet的时候 读取init-param
        String xmlPath = this.getInitParameter("struts-config");
        xmlPath = this.getServletContext().getRealPath("") + xmlPath;
        log("xmlPath: " + xmlPath);

        Map<String, ActionMapping> actionMappingMap = ConfigParseUtil.ParseStrutsConfig(xmlPath);

        this.getServletContext().setAttribute("StrutsConfigLoaded","1");
        this.getServletContext().setAttribute("StrutsConfigContent",actionMappingMap);
    }

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String reqPath = req.getRequestURI();
        reqPath = reqPath.substring(1);

        log("reqPath:" + reqPath);


        Map<String, ActionMapping> actionMappingMap = (Map<String, ActionMapping>) this.getServletContext().getAttribute("StrutsConfigContent");

        // 获取当前url匹配的actionmapping
        ActionMapping actionMapping = actionMappingMap.get(reqPath.split("\\.")[0]);

        // 封装页面input信息到actionform
        ActionForm form = this.fieldsToActionForm(req,actionMapping.getFormClass());

        Action action = this.getActionInstance(actionMapping.getActionClass());

        ActionForward forward = action.execute(req,resp,form,actionMapping);

        if (forward != null) {
            RequestDispatcher dispatcher = req.getRequestDispatcher(forward.getJspurl());
            dispatcher.forward(req,resp);
        }else{
            RequestDispatcher dispatcher = req.getRequestDispatcher("error.jsp");
            dispatcher.forward(req,resp);
        }

    }

    private Action getActionInstance(String actionClass) {
        try{
            Class c1 = Class.forName(actionClass);

            Action action = (Action)c1.newInstance();
            return action;
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            return null;
        } catch (IllegalAccessException e) {
            e.printStackTrace();
            return null;
        } catch (InstantiationException e) {
            e.printStackTrace();
            return null;
        }
    }

    private ActionForm fieldsToActionForm(HttpServletRequest req, String formClass) {
        try {
            Class c1 = Class.forName(formClass);
            ActionForm form = (ActionForm)c1.newInstance();

            Field[] fields = c1.getDeclaredFields();
            for (Field field : fields) {
                field.setAccessible(true);
                field.set(form, req.getParameter(field.getName()));
                field.setAccessible(false);
            }

            return form;
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            return null;
        } catch (IllegalAccessException e) {
            e.printStackTrace();
            return null;
        } catch (InstantiationException e) {
            e.printStackTrace();
            return null;
        }
    }


    public  void log(String msg) {
        System.out.println(msg);
    }
}
